package com.zz.admin.auth.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.zz.admin.auth.dto.BaseDataDto;
import com.zz.admin.auth.dto.DefaultUserDetails;
import com.zz.admin.auth.dto.LoginBackDto;
import com.zz.admin.auth.dto.LoginOrRegisterDto;
import com.zz.admin.auth.enums.BaseAuthExceptionEnum;
import com.zz.admin.auth.service.AuthService;
import com.zz.admin.menuManagement.dto.MenuDto;
import com.zz.admin.menuManagement.service.MenuService;
import com.zz.admin.userManagement.dto.UserDto;
import com.zz.common.constants.JwtConstant;
import com.zz.common.constants.RedisKeyConstant;
import com.zz.common.exception.ExceptionFactory;
import com.zz.common.utils.cache.RedisCacheUtils;
import com.zz.common.utils.common.TokenUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class AuthServiceImpl implements AuthService {

    @Resource
    private AuthenticationManager authenticationManager;
    @Resource
    private RedisCacheUtils redisCacheUtils;
    @Resource
    private HttpServletRequest httpServletRequest;
    @Resource
    private MenuService menuService;


    @Override
    public LoginBackDto login(LoginOrRegisterDto loginOrRegisterDto) {
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                new UsernamePasswordAuthenticationToken(loginOrRegisterDto.getLoginAccount(), loginOrRegisterDto.getPassWord());
        Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
        if (ObjectUtil.isNull(authenticate)) {
            // 验证未通过
            throw ExceptionFactory.createBaseException(BaseAuthExceptionEnum.AUTHENTICATION_IS_NULL);
        }
        DefaultUserDetails defaultUserDetails = (DefaultUserDetails) authenticate.getPrincipal();
        UserDto userDto = defaultUserDetails.getUserDto();
        // 生成token
        String token = TokenUtils.geneJsonWebToken(userDto.getUserName(), userDto.getUserId()); // 默认一小时过期
        // 生成refreshToken
        String refreshToken = TokenUtils.geneJsonWebToken(userDto.getUserName(), userDto.getUserId(), JwtConstant.JWT_REFRESH_TTL); // 默认两周过期
        // 将refreshToken存入redis
        redisCacheUtils.setCacheObject(RedisKeyConstant.REFRESH_TOKEN, refreshToken);

        // 将用户信息存储到redis中，以便于jwt校验
        redisCacheUtils.setCacheObject(RedisKeyConstant.CURRENT_USER + userDto.getUserId(), defaultUserDetails);

        return new LoginBackDto(userDto, token);
    }

    @Override
    public void logout() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if ("anonymousUser".equals(authentication.getPrincipal())) {
            return;
        }
        if (authentication.getPrincipal() instanceof DefaultUserDetails) {
            DefaultUserDetails userDetails = (DefaultUserDetails) authentication.getPrincipal();
            String userId = userDetails.getUserDto().getUserId();
            // 将redis中用户信息删除
            redisCacheUtils.deleteObject(RedisKeyConstant.CURRENT_USER + userId);
//        // 将redis中字典删除
//        redisCacheUtil.deleteObject(RedisKeyConstant.ALL_DICT);
//        redisCacheUtil.deleteObject(RedisKeyConstant.RIGHT_ORG);
        }

    }

    @Override
    public String getToken(String tokenId, HttpSession session) {
        // 从Session中获取Token
        String token = (String) session.getAttribute("token_id_" + tokenId);

        if (token == null) {
            return null;
        }

        // 删除临时Token（防止重复使用）
        session.removeAttribute("token_id_" + tokenId);
        return token;
    }

    @Override
    public String refreshToken() {
        // 从redis中获取refreshToken
        String refreshToken = redisCacheUtils.getCacheObject(RedisKeyConstant.REFRESH_TOKEN);
        if (refreshToken == null) {
            throw ExceptionFactory.createBaseException(BaseAuthExceptionEnum.REFRESH_TOKEN_IS_NULL);
        }
        // 生成新的token
        String newToken = TokenUtils.geneJsonWebToken((String) TokenUtils.parseJWT(refreshToken).get("userName"), (String) TokenUtils.parseJWT(refreshToken).get("userId"));
        return newToken;
    }

    @Override
    public BaseDataDto getBaseData(String userId) {
        // 获取菜单、组织、字典
        List<MenuDto> menuDtos = menuService.queryTreeRightMenus(userId);
//        List<DictDto> dictDtos = dictAs.queryAll();
//        Map<String, List<OrgDto>> rightOrg = orgAs.getRightOrg();
        // 将数字字典存储到redis中
//        redisCacheUtils.setCacheObject(RedisKeyConstant.ALL_DICT, dictDtos);
        // 将组织存储至redis中
//        redisCacheUtils.setCacheMap(RedisKeyConstant.RIGHT_ORG, rightOrg);
        return new BaseDataDto(menuDtos);
    }
}
